package com.dc.datacollect.helpers;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.mail.internet.MimeMessage;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.stream.Collectors;


@Component
@ConfigurationProperties(prefix = "app.notify")
class EmailListConfig {
    private List<EmailConfig> email;

    public List<EmailConfig> getEmailList() {
        return email;
    }

    public void setEmail(List<EmailConfig> email) {
        this.email = email;
    }




    @Data
    public static class EmailConfig {
        private String password;
        private String username;
        private String host;
        private Integer port;
        /**
         * 协议
         */
        private String protocol;

        /**
         * 默认编码
         */
        private String defaultEncoding;
    }
}

/**
 * 电子邮件助手
 *
 * @author zhuangjie
 * @date 2023/06/26
 */
@Component
@Slf4j
public class EmailHelper {
    @Autowired
    private void initEmailSource(EmailListConfig emailListConfig) {
        List<EmailListConfig.EmailConfig> emailList = emailListConfig.getEmailList();
        if (emailList == null || emailList.isEmpty()) {
            System.err.println("[ERROR] 您未配置邮件，发邮件功能将无法使用。");
            return;
        }



        EmailOperate.mailSenderList = emailList.stream().filter(emailConfig -> {
            // 对配置错误的，进行过滤
            String username = emailConfig.getUsername();
            String password = emailConfig.getPassword();
            String host = emailConfig.getHost();
            if (username == null || password == null || host == null) {
                if (username != null) {
                    log.error("邮箱服务：" + username + "配置不完善！将无法使用该邮箱配置发送邮件！");
                } else {
                    log.error("邮箱服务国配置错误！");
                }
                return false;
            }
            return true;
        }).map(emailConfig -> {
            // 转为服务对象
            JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
            javaMailSender.setUsername(emailConfig.getUsername());
            javaMailSender.setPassword(emailConfig.getPassword());
            javaMailSender.setHost(emailConfig.getHost());

            if (emailConfig.getPort() != null) {
                javaMailSender.setPort(emailConfig.getPort());
            }
            if (emailConfig.getProtocol() != null) {
                javaMailSender.setProtocol(emailConfig.getProtocol());
            }
            if (emailConfig.getDefaultEncoding() != null) {
                javaMailSender.setDefaultEncoding(emailConfig.getDefaultEncoding());
            }
            return javaMailSender;
        }).collect(Collectors.toList());
    }


    @Data
    public static class EmailData {
        private String subject;
        private String body;
        private String[] targetEmail;
        private MultipartFile[] attachments;
        /**
         * 邮箱发送完后回调
         */
        private Consumer<Boolean> consumer;
    }

    public static class EmailOperate {
        private EmailData emailData;
        public static List<JavaMailSenderImpl> mailSenderList;

        public EmailOperate(EmailData emailData) {
            this.emailData = emailData;
        }

        private JavaMailSenderImpl getMailSender() {
            if (mailSenderList.isEmpty()) {
                return null;
            }
            // 随机返回一个JavaMailSender
            return mailSenderList.get(new Random().nextInt(mailSenderList.size()));
        }

        /**
         * 发送单附件邮件
         *
         * @param targetEmailList 目标电子邮件
         * @param subject         主题
         * @param body            身体
         * @param attachments     附件列表
         * @return boolean
         * @throws Exception 异常
         */
        public boolean sendMail(String[] targetEmailList, String subject, String body, MultipartFile[] attachments) throws Exception {
            JavaMailSenderImpl mailSender = getMailSender();
            if (mailSender == null) {
                // 没有 MailSender 对象可用
                return false;
            }
            MimeMessage mimeMailMessage = mailSender.createMimeMessage();
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMailMessage, true);
            mimeMessageHelper.setFrom(mailSender.getUsername());
            mimeMessageHelper.setTo(targetEmailList);
            mimeMessageHelper.setSubject(subject);
            mimeMessageHelper.setText(body);
            if (attachments != null) {
                for (MultipartFile attachment : attachments) {
                    if (attachment == null) {
                        continue;
                    }
                    byte[] bytes = attachment.getBytes();
                    String name = attachment.getOriginalFilename();
                    mimeMessageHelper.addAttachment(name, new ByteArrayResource(bytes));
                }
            }
            mailSender.send(mimeMailMessage);
            return true;
        }


        public boolean send(List<String> targetEmailList) {
            if (targetEmailList == null || targetEmailList.isEmpty()) {
                return false;
            }
            String[] emails = targetEmailList.toArray(new String[targetEmailList.size()]);
            this.emailData.targetEmail = emails;
            Boolean sendResult = false;
            // 发送邮件
            try {
                sendMail(emailData.targetEmail, emailData.subject, emailData.body, emailData.attachments);
                sendResult = true;
            } catch (Exception e) {
                sendResult = false;
            } finally {
                this.emailData.consumer.accept(sendResult);
            }
            return sendResult;
        }

        public CompletableFuture<Boolean> asyncSend(List<String> targetEmailList) {
            return CompletableFuture.supplyAsync(() -> send(targetEmailList));
        }
    }

    public static class Builder {
        private EmailData emailData = new EmailData();

        public Builder(String subject, String body) {
            this.emailData.setSubject(subject);
            this.emailData.setBody(body);
        }

        public Builder files(MultipartFile... attachments) {
            this.emailData.setAttachments(attachments);
            return this;
        }
        public Builder callback(Consumer<Boolean> consumer) {
            this.emailData.setConsumer(consumer);
            return this;
        }

        public EmailOperate build() {
            return new EmailOperate(this.emailData);
        }


    }

}

